home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / dbwrend / source / val.c < prev   
C/C++ Source or Header  |  1989-04-16  |  16KB  |  394 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                  Copyright (c) 1987, David B. Wecker                 *
  4.  *                          All Rights Reserved                         *
  5.  *                                                                      *
  6.  * This file is part of DBW_Render                                      *
  7.  *                                                                      *
  8.  * DBW_Render is distributed in the hope that it will be useful, but    *
  9.  * WITHOUT ANY WARRANTY. No author or distributor accepts               *
  10.  * responsibility to anyone for the consequences of using it or for     *
  11.  * whether it serves any particular purpose or works at all, unless     *
  12.  * he says so in writing. Refer to the DBW_Render General Public        *
  13.  * License for full details.                                            *
  14.  *                                                                      *
  15.  * Everyone is granted permission to copy, modify and redistribute      *
  16.  * DBW_Render, but only under the conditions described in the           *
  17.  * DBW_Render General Public License. A copy of this license is         *
  18.  * supposed to have been given to you along with DBW_Render so you      *
  19.  * can know your rights and responsibilities. It should be in a file    *
  20.  * named COPYING. Among other things, the copyright notice and this     *
  21.  * notice must be preserved on all copies.                              *
  22.  ************************************************************************
  23.  *                                                                      *
  24.  * Authors:                                                             *
  25.  *      DBW - David B. Wecker                                           *
  26.  *                                                                      *
  27.  * Versions:                                                            *
  28.  *      V1.0 870125 DBW - First released version                        *
  29.  *                                                                      *
  30.  ************************************************************************/
  31.  
  32. #define MODULE_VAL
  33. #include "ray.h"
  34.  
  35. void getval(val,np,p,d,atten,ambientlight)
  36. vector      val,
  37.   p,
  38.   d;
  39. node        *np;
  40. float       atten;
  41. int         ambientlight;
  42. {
  43.      vector      pseudodirection,
  44.      pseudointensity,
  45.      tp,
  46.      lightdir,
  47.      lightint,
  48.      penumbra,
  49.      transparency,
  50.      best_p,
  51.      nval,
  52.      n,
  53.      r,
  54.      temp,
  55.      specintensity,
  56.      diffuse,
  57.      v1;
  58.      float       best_t,
  59.        ndotdir,
  60.        t,
  61.        texture,
  62.        td,
  63.        pointdist,
  64.        umbscale;
  65.      float       ndotd,
  66.        ambientscale;
  67.      int         hitnext,
  68.        lit,
  69.        i,
  70.        itd;
  71.      node        *bouncenp,
  72.      *occlude;
  73.      vector      light_atten[MAXLIT];
  74.      int         l_objcounter;
  75.      float       l_distances[MAXOBJ];
  76.      node        *l_objpairs[MAXOBJ];
  77.      vector      l_points[MAXOBJ];
  78.  
  79.      if (allopaque == 0) 
  80.      { /* If not opaque,then save the ray intersection list */
  81.           l_objcounter = g_objcounter;
  82.           for (i = 0; i < l_objcounter; i++) 
  83.           {
  84.                l_distances[i] = g_distances[i];
  85.                l_objpairs[i] = g_objpairs[i];
  86.                veccopy(g_points[i],l_points[i]);
  87.           }
  88.      }
  89.  
  90.      veczero(val);  /* start with output value of zero */
  91.  
  92.      findnormal(np,p,n);
  93.      ndotd = DOT(n,d);
  94.      if (ndotd > 0.0) 
  95.      {          /* We're looking at surface's back side */
  96.           ndotd = -ndotd;
  97.           n[0] = -n[0];  /* Flip the normal */
  98.           n[1] = -n[1];
  99.           n[2] = -n[2];
  100.      }
  101.  
  102.      /* Initialize the light attenuation values with 'not-yet-computed' flag */
  103.  
  104.      for (lit = 0; lit < numlits; lit++)
  105.           light_atten[lit][0] = -99.9;
  106.  
  107.      /* Apply procedural texture */
  108.      gettex(diffuse,np,p,n);
  109.  
  110.      /*---------------------------------------------------------------------*/
  111.      /* Compute diffuse reflection intensity */
  112.  
  113.      if (diffuse[0] > 0.01 || diffuse[1] > 0.01 || diffuse[2] > 0.01) 
  114.      {
  115.  
  116.           /* First,compute light shining directly on this point */
  117.           for (lit = 0; lit < numlits; lit++) 
  118.           { 
  119.                veccopy(light[lit].direction,lightdir);
  120.                veccopy(light[lit].intensity,lightint);
  121.  
  122.                pointdist = 0.0;
  123.  
  124.                if (light[lit].kind != 0) 
  125.                { /* If point source,compute local direction */
  126.                     vecsub(lightdir,p,lightdir);
  127.                     pointdist = NORM(lightdir);  /* distance to point light source */
  128.                     if (pointdist == 0.0)
  129.                          pointdist = 0.01;
  130.                     umbscale  = light[lit].distscale;
  131.                     umbscale /= pointdist * pointdist;
  132.                     vecscale(umbscale,lightint,lightint);
  133.                     CV(rnd(),rnd(),rnd(),penumbra);
  134.                     if (rnd() < 0.5)
  135.                          penumbra[0] = -penumbra[0];
  136.                     if (rnd() < 0.5)
  137.                          penumbra[1] = -penumbra[1];
  138.                     if (rnd() < 0.5)
  139.                          penumbra[2] = -penumbra[2];
  140.                     normalize(penumbra);  /* penumbra is now random unit vector */
  141.  
  142.                     umbscale  = rnd();
  143.                     umbscale -= 0.05;
  144.                     umbscale *= light[lit].radius;
  145.                     vecscale(umbscale,penumbra,penumbra);
  146.                     vecsum(penumbra,lightdir,lightdir);
  147.                     normalize(lightdir);
  148.                }
  149.  
  150.                /* Now that we know where the light is shining from,compute diffuse
  151.                (lamertian) reflection */
  152.  
  153.                ndotdir = DOT(n,lightdir);
  154.                if (ndotdir > 0.0) 
  155.                {
  156.                     vecmul(lightint,diffuse,nval);
  157.                     vecscale(ndotdir,nval,nval);
  158.                }
  159.                else
  160.                {
  161.                     veczero(nval);  /* self shadowing -- backside of spheres,etc. */
  162.                }
  163.  
  164.                /* If the computed diffuse surface brightness is above a certain
  165.                threshold level,then compute the shadow attenuation */
  166.  
  167.                if (nval[0] > 0.01 || nval[1] > 0.01 || nval[2] > 0.01) 
  168.                {
  169.                     getatten(light_atten[lit],p,lightdir,lit,pointdist);
  170.                     vecmul(nval,light_atten[lit],nval); /* attenuate */
  171.                }
  172.                vecsum(nval,val,val);  /* Sum up for all light sources */
  173.           } /* for */
  174.  
  175.           /*---------------------------------------------------------------------*/
  176.           /* Next,compute light shining indirectly from any surfaces on this    */
  177.           /* point.  This is done to approximate true ambient illumination.      */
  178.  
  179.           for (lit = 0; lit < ambientlight; lit++) 
  180.           {
  181.                ambientscale = 1.0 / (float) ambientlight;
  182.                /* ?? not sure how to factor in distance from diffuse reflector */
  183.  
  184.                CV(rnd(),rnd(),rnd(),lightdir);
  185.                if (rnd() < 0.5)
  186.                     lightdir[0] = -lightdir[0];
  187.                if (rnd() < 0.5)
  188.                     lightdir[1] = -lightdir[1];
  189.                if (rnd() < 0.5)
  190.                     lightdir[2] = -lightdir[2];
  191.                normalize(lightdir);  /* lightdir is now random unit vector */
  192.  
  193.                ndotdir = DOT(n,lightdir);
  194.                if (ndotdir < 0.0) 
  195.                { /* if not in upper hemisphere,invert it */
  196.                     lightdir[0] = -lightdir[0];
  197.                     lightdir[1] = -lightdir[1];
  198.                     lightdir[2] = -lightdir[2];
  199.                     ndotdir = -ndotdir;
  200.                }
  201.  
  202.                /* okay,now the direction is known.  What is visible there? */
  203.                dodirection(nval,p,lightdir,ambientscale,
  204.                  ambientlight * amblitnum / amblitdenom);
  205.  
  206.                val[0] += nval[0] * ndotdir * diffuse[0];
  207.                val[1] += nval[1] * ndotdir * diffuse[1];
  208.                val[2] += nval[2] * ndotdir * diffuse[2];
  209.  
  210.           } /* for */
  211.  
  212.  
  213.           /*---------------------------------------------------------------------*/
  214.           /* Next,compute light shining indirectly from mirrors on this point   */
  215.  
  216.           if (dopseudo) 
  217.           {
  218.                for (lit = 0; lit < numlits; lit++) 
  219.                { /* for each true light... */
  220.                     bouncenp = root;
  221.                     while (bouncenp) 
  222.                     { /* for each possible mirror... */
  223.                          if (bouncelighting(pseudointensity,pseudodirection,bouncenp,lit)
  224.                            && bouncenp != np) 
  225.                          { /* don't check reflections from ourselves */
  226.                               /* Okay,this object reflects light.  Does any of it reach us? */
  227.                               CV(1.0,1.0,1.0,transparency);
  228. #ifdef MCH_AMIGA
  229.                               occlude = 1L;
  230. #else
  231.                               occlude = (node *)1L;
  232. #endif
  233.                               hitnext = 0;
  234.                               all_intersects(p,pseudodirection,0);
  235.  
  236.                               while (occlude &&  (transparency[0] > 0.01 ||
  237.                                 transparency[1] > 0.01 ||
  238.                                 transparency[2] > 0.01)) 
  239.                               {
  240.                                    if (occlude = get_next_intersection(hitnext,best_p,&best_t)) 
  241.                                    {
  242.                                         /* pseudolight intersects an object,see if any passes through */
  243.                                         if (occlude == bouncenp)
  244.                                              occlude = 0;  /* hit the mirror causing the pseudolight,stop */
  245.                                         else
  246.                                         {
  247.                                              vecmul(transparency,occlude->attr.tra,
  248.                                                transparency);
  249.                                              hitnext++;
  250.                                         }
  251.                                    }
  252.                                    else
  253.                                    {
  254.                                         /* no more objects to intersect -- we didn't intersect the mirror
  255.                                         that is causing the pseudolight,so cancel the pseudolight */
  256.                                         veczero(transparency);
  257.                                    }
  258.                               }
  259.  
  260.                               if (transparency[0] > 0.01 || transparency[1] > 0.01 ||
  261.                                 transparency[2] > 0.01) 
  262.                               {
  263.                                    ndotdir = DOT(n,pseudodirection);
  264.                                    if (ndotdir > 0.0) 
  265.                                    {
  266.                                         for (i = 0; i < 3; i++)
  267.                                              val[i] += transparency[i] * pseudointensity[i] * 
  268.                                                ndotdir * diffuse[i];
  269.                                    }
  270.                               }
  271.                          } /* if */
  272.                          bouncenp = bouncenp->next;  /* next possible mirror */
  273.                     } /* while */
  274.                } /* for */
  275.           } /* if dopseudo */
  276.      } /* if any diffuse reflectivity */
  277.  
  278.      /*---------------------------------------------------------------------*/
  279.      /* Compute mirror & specular reflection intensity */
  280.  
  281.      atten *= np->attr.ref;  /* factor in the object's relative reflectivity */
  282.  
  283.      if (atten > 0.01) 
  284.      { /* Is object meaningfully reflective still */
  285.           vecscale(2 * ndotd,n,r);
  286.           vecsub(d,r,r);
  287.  
  288.           dodirection(nval,p,r,atten,ambientlight);  /* Mirror reflection */
  289.           vecscale(atten,nval,nval);  /* attenuate by reflectivity coeff */
  290.  
  291.           /* We really want Fresnel angle factor here,but... */
  292.           if (np->kind == SPHERE) 
  293.           { /* Add sparkle */
  294.                t = DOT(n,r);
  295.                if (t >= 0.0) 
  296.                {
  297.                     veccopy(nval,specintensity);
  298.                     t = 1.0 - t;
  299.                     t = t * t * t * t * t;
  300.                     vecscale(t,specintensity,specintensity);
  301.                     vecsum(nval,specintensity,nval);
  302.                }
  303.           }
  304.  
  305.           /* Compute specular reflection intensity */
  306.  
  307.           for (lit = 0; lit < numlits; lit++) 
  308.           {
  309.                veccopy(light[lit].direction,lightdir);
  310.                veccopy(light[lit].intensity,lightint);
  311.                pointdist = 0.0;
  312.  
  313.                if (light[lit].kind != 0) 
  314.                { /* If point source,compute local direction */
  315.                     vecsub(lightdir,p,lightdir);
  316.                     pointdist = NORM(lightdir);  /* distance to point light source */
  317.                     if (pointdist == 0.0)
  318.                          pointdist = 0.01;
  319.                     umbscale  = light[lit].distscale;
  320.                     umbscale /= pointdist * pointdist;
  321.                     vecscale(umbscale,lightint,lightint);
  322.                     normalize(lightdir);
  323.                }
  324.  
  325.                t = DOT(lightdir,r);
  326.                if (t > 0.0) 
  327.                {              /* Check self-shadowing */
  328.                     if (np->attr.fuz == 0.0)
  329.                          td = 1000.0;  /* extremely smooth mirror */
  330.                     else
  331.                     {
  332.                          td = 2.0/np->attr.fuz;  /* calc specular decay rate based on fuz */
  333.                          if (td < 1.0)
  334.                               td = 1.0;
  335.                     }
  336.  
  337.                     t = pow(t,td)  /* calc reflectivity for desired gloss */
  338.                       * atten;  /* attenuate specular reflections by reflectivity coeff */
  339.  
  340.                     if (t > 0.01) 
  341.                     { /* specular coefficient is meaningful,add it */
  342.                          /* first compute shadowing of light source causing specular refl. */
  343.                          if (light_atten[lit][0] < 0.0)  /* Not already computed,compute */
  344.                               getatten(light_atten[lit],p,lightdir,lit,pointdist);
  345.  
  346.                          nval[0] += lightint[0] * light_atten[lit][0] * t;
  347.                          nval[1] += lightint[1] * light_atten[lit][1] * t;
  348.                          nval[2] += lightint[2] * light_atten[lit][2] * t;
  349.                     }
  350.                }
  351.           }
  352.  
  353.           vecsum(nval,val,val); /* Add mirror/specular reflections to running total */
  354.      } /* if reflective atten is non-zero */
  355.  
  356.  
  357.  
  358.      /*----------------------------------------------------------------------*/
  359.      /* Add in the object's ambient intensity */
  360.      if (ambscale < 0.0) 
  361.      {
  362.           vecsum(np->attr.amb,val,val);
  363.      }
  364.      else
  365.      { /* use specified computed ambient */
  366.           val[0] += diffuse[0] * ambscale;
  367.           val[1] += diffuse[1] * ambscale;
  368.           val[2] += diffuse[2] * ambscale;
  369.      }
  370.  
  371.      /*---------------------------------------------------------------------*/
  372.      /* Apply any post-process global texture functions */
  373.  
  374.      if (numhazes > 0) 
  375.      {
  376.           /* Blend the final color toward the specified haze color */
  377.           vecsub(p,eye,temp);
  378.           texture  = NORM(temp);  /* distance to point from eye */
  379.           texture /= haze[numhazes-1].distscale;  /* scaled according to user */
  380.           blendcolor(val,haze[numhazes-1].color,texture,val);
  381.      }
  382.  
  383.      if (allopaque == 0) 
  384.      { /* If not opaque,then restore the ray intersection list */
  385.           g_objcounter = l_objcounter;
  386.           for (i = 0; i < g_objcounter; i++) 
  387.           {
  388.                g_distances[i] = l_distances[i];
  389.                g_objpairs[i] = l_objpairs[i];
  390.                veccopy(l_points[i],g_points[i]);
  391.           }
  392.      }
  393. }
  394.